#include "RenderWidget.h"
#include <cmath>
#include <QCursor> //Qt 光标控制，用于交互时修改光标样式

// 着色器源码
static const char *vertSrc = R"(
#version 330 core
layout(location=0) in vec2 aPos;
uniform mat4 uMVP;
void main(){ gl_Position = uMVP * vec4(aPos,0,1); }
)";// 顶点着色器：接收 aPos（二维坐标），通过 uMVP 矩阵变换顶点位置
static const char *fragSrc = R"(
#version 330 core
uniform vec3 uColor;
out vec4 FragColor;
void main(){ FragColor = vec4(uColor,1); }
)";//片段着色器：固定输出颜色 uColor，暂无光照或纹理

//构造函数 初始化缓冲区对象，设置定时器用于动画效果线条
RenderWidget::RenderWidget(QWidget *parent)
    : QOpenGLWidget(parent)
    , axisVbo_(QOpenGLBuffer::VertexBuffer)
    , tickVbo_(QOpenGLBuffer::VertexBuffer)
    , animVbo_(QOpenGLBuffer::VertexBuffer)
{
    setFocusPolicy(Qt::StrongFocus); // 允许键盘事件
    growthTimer_ = new QTimer(this);   // 动画定时器
    connect(growthTimer_, &QTimer::timeout, this, [this]() {
        growthFactor_ += 0.02f;       // 线性增长因子（0~1）
        if (growthFactor_ >= 1.0f) {
            growthFactor_ = 1.0f;
            growthTimer_->stop();
        }
        update();
    });
}
//析构函数 清理 OpenGL 资源，避免内存泄漏。
RenderWidget::~RenderWidget() {
    makeCurrent();
    axisVbo_.destroy(); axisVao_.destroy();
    tickVbo_.destroy(); tickVao_.destroy();
    animVbo_.destroy(); animVao_.destroy();
    doneCurrent();
}

//OpenGL 初始化
void RenderWidget::initializeGL() {
    initializeOpenGLFunctions();  // 初始化 OpenGL 函数指针
    glClearColor(1,1,1,1);    // 设置清屏颜色为白色
    initShaders();           // 编译链接着色器
    buildAxisGeometry();    // 构建坐标轴几何数据
    buildTickGeometry();  //构建刻度几何数据
    // 动画 VAO/VBO 初始化
    animVao_.create(); animVao_.bind();
    animVbo_.create(); animVbo_.bind();
    shaderProgram_.enableAttributeArray(0);
    shaderProgram_.setAttributeBuffer(0, GL_FLOAT, 0, 2);
    animVbo_.release(); animVao_.release();
}

//窗口大小调整，根据窗口尺寸调整正交投影矩阵，保持坐标轴比例正确。
void RenderWidget::resizeGL(int w, int h) {
    glViewport(0,0,w,h);
    aspect_ = float(w)/float(h);
    projection_.setToIdentity(); // 重置投影矩阵
    projection_.ortho(-aspect_, aspect_, -1, 1, -1, 1); // 正交投影
    updateMatrices();  // 更新 MVP 矩阵
}

//渲染主循环
void RenderWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);
    shaderProgram_.bind(); // 绑定着色器
    shaderProgram_.setUniformValue("uMVP", projection_ * view_ * model_);
    // 传递 MVP 矩阵
    drawAxes(); // 根据标志绘制不同内容
    // 根据标志绘制不同内容
    if (displaySum_)    drawSum();
    if (displayMatrix_) drawMatrix();
    if (displayLU_)     drawLU();
    if (displayQR_)     drawQR();
    if (displayEigen_)  drawEigen();
    if (displaySolution_) drawSolution();
    shaderProgram_.release();  // 解绑着色器
}
// 交互环节
// 1.鼠标按下：记录起始位置，切换光标样式
void RenderWidget::mousePressEvent(QMouseEvent *e) {
    if (e->button() == Qt::LeftButton) {
        setCursor(Qt::ClosedHandCursor);  // 按下显示实心手
        lastPos_ = e->pos();
        dragging_ = true;
    }
    QOpenGLWidget::mousePressEvent(e);
}
// 2.鼠标释放：恢复光标样式
void RenderWidget::mouseReleaseEvent(QMouseEvent *e) {
    if (e->button() == Qt::LeftButton) {
        dragging_ = false;
        setCursor(Qt::ArrowCursor);      // 恢复默认箭头
    }
    QOpenGLWidget::mouseReleaseEvent(e);
}
// 3.鼠标拖动：计算平移量，更新视图矩阵
void RenderWidget::mouseMoveEvent(QMouseEvent *e) {
    if (dragging_) {
        QPoint d = e->pos() - lastPos_;
        panX_ += 2.0f*d.x()/width();  // 归一化平移量
        panY_ -= 2.0f*d.y()/height();
        lastPos_ = e->pos();
        updateMatrices();  // 更新视图矩阵
        update();       // 触发重绘
    }
}
// 4.滚轮事件：缩放视图
void RenderWidget::wheelEvent(QWheelEvent *e) {
    float delta = e->angleDelta().y()/120.0f;  // 计算滚轮增量
    scaleFactor_ *= pow(1.1f, delta);  // 调整缩放因子
    updateMatrices(); update();
}
// 5.键盘事件：+/- 控制缩放
void RenderWidget::keyPressEvent(QKeyEvent *e) {
    if (e->key()==Qt::Key_Plus)      adjustScale(+0.1f);
    else if (e->key()==Qt::Key_Minus) adjustScale(-0.1f);
}

//辅助函数
// 1.初始化着色器
void RenderWidget::initShaders() {
    shaderProgram_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertSrc);
    shaderProgram_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragSrc);
    shaderProgram_.link();
}
// 2.构建坐标轴几何数据（动态更新，无需预定义）
void RenderWidget::buildAxisGeometry() {
    axisVao_.create(); axisVao_.bind();
    axisVbo_.create(); axisVbo_.bind();
    GLfloat dummy[8] = {0};
    axisVbo_.allocate(dummy, sizeof(dummy));
    shaderProgram_.enableAttributeArray(0);
    shaderProgram_.setAttributeBuffer(0, GL_FLOAT, 0, 2);
    axisVbo_.release(); axisVao_.release();
}
// 3.构建刻度几何数据（预定义静态数据）
void RenderWidget::buildTickGeometry() {
    const float step = 0.2f;
    QVector<GLfloat> verts;
    for (float i = -1.0f; i <= 1.0f; i += step) {
        verts << i << -0.03f << i << 0.03f;
        verts << -0.03f << i << 0.03f << i;
    }
    tickCount_ = verts.size()/2;
    tickVao_.create(); tickVao_.bind();
    tickVbo_.create(); tickVbo_.bind();
    tickVbo_.allocate(verts.constData(), verts.size()*sizeof(GLfloat));
    shaderProgram_.enableAttributeArray(0);
    shaderProgram_.setAttributeBuffer(0, GL_FLOAT, 0, 2);
    tickVbo_.release(); tickVao_.release();
}
// 4.更新视图矩阵（平移 + 缩放）
void RenderWidget::updateMatrices() {
    view_.setToIdentity();
    view_.translate(panX_, panY_, 0);  // 平移
    view_.scale(scaleFactor_, scaleFactor_, 1);  // 缩放
    model_.setToIdentity();
}
void RenderWidget::adjustScale(float d) {
    scaleFactor_ = qBound(0.1f, scaleFactor_+d, 10.0f);
    updateMatrices(); update();
}

// 绘制函数
// 1.绘制坐标轴、刻度和箭头
void RenderWidget::drawAxes() {
    // 动态生成坐标轴线段
    GLfloat axes[8] = {
        -aspect_, 0, aspect_, 0,
        0, -1, 0, 1
    };
    axisVao_.bind(); axisVbo_.bind();
    axisVbo_.allocate(axes, sizeof(axes)); // 更新坐标轴数据
    shaderProgram_.setUniformValue("uColor", QVector3D(0.1f,0.1f,0.1f));
    // 绘制刻度和箭头
    glLineWidth(2.5f); glDrawArrays(GL_LINES, 0, 4);
    axisVbo_.release(); axisVao_.release();
    // ticks
    tickVao_.bind();
    shaderProgram_.setUniformValue("uColor", QVector3D(0.1f,0.1f,0.1f));
    glLineWidth(1.5f); glDrawArrays(GL_LINES, 0, tickCount_);
    tickVao_.release();
    // arrows
    drawAxisArrows();
}
    //绘制三角形作为箭头
void RenderWidget::drawAxisArrows() {
    GLfloat ax[6] = { aspect_, 0.05f, aspect_, -0.05f, aspect_+0.05f, 0 };
    drawArrow(ax);
    GLfloat ay[6] = { -0.05f, 1.0f, 0.05f, 1.0f, 0.0f, 1.05f };
    drawArrow(ay);
}

// 2.绘制动画线条
void RenderWidget::drawAnimatedLine(const QVector2D &to, const QVector3D &color) {
    if (growthFactor_ <= 0) return;
    QVector2D end = to * growthFactor_; // 根据动画因子截断线条
    GLfloat verts[4] = {0, 0, end.x(), end.y()};
    animVao_.bind(); animVbo_.bind();
    animVbo_.allocate(verts, sizeof(verts));  // 更新动画线条数据
    shaderProgram_.setUniformValue("uColor", color);
    glLineWidth(3.0f); glDrawArrays(GL_LINES, 0, 2);
    animVbo_.release(); animVao_.release();
}

// 1）绘制向量和
void RenderWidget::drawSum() {
    drawAnimatedLine(QVector2D(vector1_), QVector3D(1,0,0));
    drawAnimatedLine(QVector2D(vector2_), QVector3D(0,0,1));
    drawAnimatedLine(QVector2D(vector1_)+QVector2D(vector2_), QVector3D(0,1,0));
}
// 2）绘制矩阵
void RenderWidget::drawMatrix() {
    QMatrix4x4 M;
    M.setRow(0, QVector4D(matrix_.x(), matrix_.y(), 0, 0));
    M.setRow(1, QVector4D(matrix_.z(), matrix_.w(), 0, 0));
    drawAnimatedLine((M*QVector4D(1,0,0,1)).toVector2D(), QVector3D(1,0.5f,0));
    drawAnimatedLine((M*QVector4D(0,1,0,1)).toVector2D(), QVector3D(0.5f,0,1));
}
// 3）绘制LU
void RenderWidget::drawLU() {
    drawAnimatedLine(QVector2D(luL_(0,0), luL_(1,0)), QVector3D(0,1,1));
    drawAnimatedLine(QVector2D(luL_(0,1), luL_(1,1)), QVector3D(1,1,0));
    drawAnimatedLine(QVector2D(luU_(0,0), luU_(0,1)), QVector3D(1,0,1));
    drawAnimatedLine(QVector2D(luU_(1,0), luU_(1,1)), QVector3D(0,1,0));
}
// 4）绘制QR
void RenderWidget::drawQR() {
    drawAnimatedLine(QVector2D(qrQ_(0,0), qrQ_(1,0)), QVector3D(0,0.5f,0.5f));
    drawAnimatedLine(QVector2D(qrQ_(0,1), qrQ_(1,1)), QVector3D(0.5f,0,0.5f));
    drawAnimatedLine(QVector2D(qrR_(0,0), qrR_(0,1)), QVector3D(0.5f,0.5f,0));
    drawAnimatedLine(QVector2D(qrR_(1,0), qrR_(1,1)), QVector3D(1,0.5f,0));
}
// 5）绘制Eigen
void RenderWidget::drawEigen() {
    drawAnimatedLine(QVector2D(eigVecs_(0,0), eigVecs_(1,0)), QVector3D(0.7f,0.2f,0.7f));
    drawAnimatedLine(QVector2D(eigVecs_(0,1), eigVecs_(1,1)), QVector3D(0.2f,0.7f,0.7f));
}
// 6)绘制方程解
void RenderWidget::drawSolution() {
    drawAnimatedLine(solution_, QVector3D(1,0.3f,0));
}

// 数据更新与动画控制
void RenderWidget::drawArrow(const GLfloat arrow[6]) {
    QOpenGLBuffer tmpV(QOpenGLBuffer::VertexBuffer);
    QOpenGLVertexArrayObject tmpA;
    tmpA.create(); tmpA.bind();
    tmpV.create(); tmpV.bind();
    tmpV.allocate(arrow, 6*sizeof(GLfloat));
    shaderProgram_.enableAttributeArray(0);
    shaderProgram_.setAttributeBuffer(0, GL_FLOAT, 0, 2);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    tmpV.release(); tmpA.release();
}

void RenderWidget::showVectorSum(const QPointF &v1, const QPointF &v2) {
    vector1_=v1; vector2_=v2; displaySum_=true;
    displayMatrix_=displayLU_=displayQR_=displayEigen_=displaySolution_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::showMatrixTransform(const QVector4D &m) {
    matrix_=m; displayMatrix_=true;
    displaySum_=displayLU_=displayQR_=displayEigen_=displaySolution_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::showLU(const Eigen::Matrix2f &L, const Eigen::Matrix2f &U) {
    luL_=L; luU_=U; displayLU_=true;
    displaySum_=displayMatrix_=displayQR_=displayEigen_=displaySolution_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::showQR(const Eigen::Matrix2f &Q, const Eigen::Matrix2f &R) {
    qrQ_=Q; qrR_=R; displayQR_=true;
    displaySum_=displayMatrix_=displayLU_=displayEigen_=displaySolution_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::showEigen(const Eigen::Vector2f &values, const Eigen::Matrix2f &vectors) {
    eigVals_=values; eigVecs_=vectors; displayEigen_=true;
    displaySum_=displayMatrix_=displayLU_=displayQR_=displaySolution_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::showSolution(const QVector2D &sol) {
    solution_=sol; displaySolution_=true;
    displaySum_=displayMatrix_=displayLU_=displayQR_=displayEigen_=false;
    growthFactor_=0; QTimer::singleShot(0,this,[this](){growthTimer_->start(16);});
}

void RenderWidget::resetView() {
    panX_ = panY_ = 0; scaleFactor_ = 1;
    updateMatrices(); update();
}

void RenderWidget::clearTransform() {
    displayMatrix_ = false; update();
}

void RenderWidget::clearSolution() {
    displaySolution_ = false; update();
}

